package main

import (
	"database/sql"
	"fmt"
	pb "ihos/ihos"
	"log"

	tm "github.com/golang/protobuf/ptypes/timestamp"
	"github.com/lib/pq"
)

type houzhen_paidui struct {
	id     int32         //PK
	paiban int32         //门诊排班
	riqi   int64         //排队日期
	guahao int32         //挂号ID
	yonghu pq.Int64Array //用此号排队的用户
	status int32         //叫号状态
	doctor int32         //问诊医生ID
	paihao int32         //排队序号
	remain int32         //前面还有几个号
}

func (d *houzhen_paidui) GetFromDB(id int32) error {
	sql := "SELECT id,paiban,riqi,guahao,yonghu,status,doctor,paihao FROM houzhen_paidui WHERE id=$1"
	return DBConn.db.QueryRow(sql, id).Scan(&d.id, &d.paiban, &d.riqi, &d.guahao, &d.yonghu, &d.status, &d.doctor, &d.paihao)
}

func (d *houzhen_paidui) SaveToDB(id int32) error {
	sql := ""
	var err error
	if id > 0 { //update
		sql = "UPDATE houzhen_paidui set paiban=$1,riqi=$2,guahao=$3,yonghu=$4,status=$5,doctor=$6,paihao=$7 where id=$8 RETURNING id"
		err = DBConn.db.QueryRow(sql, d.paiban, d.riqi, d.guahao, d.yonghu, d.status, d.doctor, d.paihao, d.id).Scan(&d.id)
	} else { //insert
		sql = "INSERT INTO houzhen_paidui(paiban,riqi,guahao,yonghu,status,doctor,paihao)VALUES($1,$2,$3,$4,$5,$6,$7) RETURNING id"
		err = DBConn.db.QueryRow(sql, d.paiban, d.riqi, d.guahao, d.yonghu, d.status, d.doctor, d.paihao).Scan(&d.id)
	}
	return err
}

func (d *houzhen_paidui) UpdateYongHu() error {
	sql := ""
	var err error
	if d.id > 0 { //update
		sql = "UPDATE houzhen_paidui set yonghu=$1 where id=$2 RETURNING id"
		err = DBConn.db.QueryRow(sql, d.yonghu, d.id).Scan(&d.id)
	}
	return err
}

func (d *houzhen_paidui) UpdateDoctor() error {
	sql := ""
	var err error
	if d.id > 0 { //update
		sql = "UPDATE houzhen_paidui set doctor=$1 where id=$2 RETURNING id"
		err = DBConn.db.QueryRow(sql, d.doctor, d.id).Scan(&d.id)
	}
	return err
}

func (d *houzhen_paidui) UpdateStatus() error {
	sql := ""
	var err error
	if d.id > 0 { //update
		sql = "UPDATE houzhen_paidui set status=$1 where id=$2 RETURNING id"
		err = DBConn.db.QueryRow(sql, d.status, d.id).Scan(&d.id)
	}
	return err
}

func (d *houzhen_paidui) Get() error {
	sql := "SELECT id,paiban,riqi,guahao,yonghu,status,doctor,paihao FROM houzhen_paidui WHERE paiban=$1 AND riqi=$2 AND guahao=$3"
	return DBConn.db.QueryRow(sql, d.paiban, d.riqi, d.guahao).Scan(&d.id, &d.paiban, &d.riqi, &d.guahao, &d.yonghu, &d.status, &d.doctor, &d.paihao)
}

func (d *houzhen_paidui) GetByGuaHao() error {
	sql := "SELECT id,paiban,riqi,guahao,yonghu,status,doctor,paihao FROM houzhen_paidui WHERE riqi=$1 AND guahao=$2"
	return DBConn.db.QueryRow(sql, d.riqi, d.guahao).Scan(&d.id, &d.paiban, &d.riqi, &d.guahao, &d.yonghu, &d.status, &d.doctor, &d.paihao)
}

func (d *houzhen_paidui) GetPaiHaoLast() error {
	// log.Println("GetPaiHaoLast")
	sql := "SELECT paihao FROM houzhen_paidui WHERE paiban=$1 AND riqi=$2 order by paihao desc limit 1"
	return DBConn.db.QueryRow(sql, d.paiban, d.riqi).Scan(&d.paihao)
}

func (d *houzhen_paidui) GetPaiDuiList() (phs []*houzhen_paidui, err error) {
	// log.Println("GetPaiDuiList:", d)
	var rows *sql.Rows
	out := make([]*houzhen_paidui, 0)
	sqlStr := ""
	if d.id > 0 {
		sqlStr = "SELECT id,paiban,riqi,guahao,yonghu,status,doctor,paihao FROM houzhen_paidui WHERE id=" + fmt.Sprint(d.id)
	} else {
		sqlStr = "SELECT id,paiban,riqi,guahao,yonghu,status,doctor,paihao FROM houzhen_paidui"
		cond := make([]string, 0)
		if d.paiban > 0 {
			cond = append(cond, "paiban="+fmt.Sprint(d.paiban))
		}
		if d.riqi > 0 {
			cond = append(cond, "riqi="+fmt.Sprint(d.riqi))
		}
		if d.guahao > 0 {
			cond = append(cond, "guahao="+fmt.Sprint(d.guahao))
		}
		if d.remain > 0 {
			cond = append(cond, "ARRAY_LENGTH(yonghu,1)>0")
		}
		if len(cond) > 0 {
			sqlStr += " WHERE "
			sep := ""
			for _, v := range cond {
				sqlStr += sep + v
				sep = " AND "
			}
		}
		sqlStr += " ORDER BY id LIMIT 500"
	}
	// log.Println("SQL:", sqlStr)
	rows, err = DBConn.db.Query(sqlStr)
	if err != nil {
		log.Println("err1:", err)
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		w := &houzhen_paidui{}
		if err = rows.Scan(&w.id, &w.paiban, &w.riqi, &w.guahao, &w.yonghu, &w.status, &w.doctor, &w.paihao); err != nil {
			log.Println("err2:", err)
		} else {
			out = append(out, w)
		}
	}
	// log.Println("OUT:", out)
	return out, nil
}

func (d *houzhen_paidui) Save() error {
	t := &houzhen_paidui{
		paiban: d.paiban,
		riqi:   d.riqi,
		guahao: d.guahao,
	}
	if err := t.Get(); err != nil {
		return d.SaveToDB(0)
	} else {
		d.id = t.id
		return d.SaveToDB(d.id)
	}
}

func (w *houzhen_paidui) toPB() *pb.HouZhenPaiDui {
	w.remain = menZhenPaiDui.GetRemain(w.id)
	h := &pb.HouZhenPaiDui{
		ID:     w.id,
		PAIBAN: &pb.MenZhenPaiBan{ID: w.paiban},
		RIQI:   &tm.Timestamp{Seconds: w.riqi},
		GUAHAO: &pb.GuaHao{ID: w.guahao},
		YONGHU: make([]*pb.ShiPinYongHuL5, 0),
		STATUS: w.status,
		DOCTOR: &pb.YiShengInfoL3{ID: w.doctor},
		PAIHAO: w.paihao,
		REMAIN: w.remain,
	}
	// p := &menzhen_paiban{id: w.paiban}
	// if p.id > 0 {
	// 	if err := p.GetFromDB(p.id); err != nil {
	// 		log.Println("1:", err)
	// 		return nil
	// 	} else {
	// 		h.PAIBAN = p.toPB()
	// 	}
	// }
	g := &guahao{id: w.guahao}
	if g.id > 0 {
		if err := g.GetFromDB(g.id); err != nil {
			log.Println("2:", err)
			return nil
		} else {
			h.GUAHAO = g.toPB()
		}
	}
	for _, v := range w.yonghu {
		if v > 0 {
			y := &shipin_yonghu{id: int32(v)}
			if err := y.GetFromDB(y.id); err != nil {
				log.Println("3:", err)
				return nil
			} else {
				h.YONGHU = append(h.YONGHU, y.toPB())
			}
		}
	}
	// d := &yisheng{id: w.doctor}
	// if d.id > 0 {
	// 	if err := d.GetFromDB(d.id); err != nil {
	// 		log.Println("4:", err)
	// 		return nil
	// 	} else {
	// 		h.DOCTOR = d.toPB()
	// 	}
	// }
	return h
}

func (w *houzhen_paidui) fromPB(p *pb.HouZhenPaiDui) *houzhen_paidui {
	//登录名称唯一，如果存在则读取记录，获得ID
	w.id = p.GetID()
	w.paiban = p.GetPAIBAN().GetID()
	w.riqi = p.GetRIQI().GetSeconds()
	w.guahao = p.GetGUAHAO().GetID()
	w.yonghu = make([]int64, 0)
	for _, v := range p.GetYONGHU() {
		if v.GetYHID() > 0 {
			w.yonghu = append(w.yonghu, int64(v.GetYHID()))
		}
	}
	w.status = p.GetSTATUS()
	w.doctor = p.GetDOCTOR().GetID()
	w.paihao = p.GetPAIHAO()
	w.remain = p.GetREMAIN()
	return w
}
